﻿namespace BassettData.Robots.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using FluentAssertions;
    using NUnit.Framework;

    public class UrRobotBehaviour
    {
        [Test]
        public void CanTurnOffAndFindWhereWeAre()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);
            string result = karel.TurnOff();

            result.Should().Contain("Robot Karel is at Avenue 1, Street 1");
        }

        [Test]
        public void MustBeTurnedOnToMove()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);

            karel.TurnOff();
            Assert.Throws<InvalidOperationException>(() => karel.Move());
        }

        [Test]
        public void MustBeTurnedOnToTurn()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);

            karel.TurnOff();
            Assert.Throws<InvalidOperationException>(() => karel.TurnLeft());
        }

        [Test]
        public void CanMoveInDefaultDirectionEast()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);

            karel.Move();
            karel.TurnOff();

            karel.Location.Avenue.Should().Be(2);
            karel.Location.Street.Should().Be(1);
        }

        [Test]
        public void CanTurnAndGoNorth()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);

            karel.TurnLeft();
            karel.Move();
            karel.TurnOff();

            karel.Location.Avenue.Should().Be(1);
            karel.Location.Street.Should().Be(2);
        }

        [Test]
        public void CannotMoveOffWorldToTheWest()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);

            karel.TurnLeft();
            karel.TurnLeft();

            Assert.Throws<InvalidOperationException>(() => karel.Move());
            karel.TurnOff();

            karel.Location.Avenue.Should().Be(1);
            karel.Location.Street.Should().Be(1);
        }

        [Test]
        public void CannotMoveOffWorldToTheSouth()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);

            karel.TurnLeft();
            karel.TurnLeft();
            karel.TurnLeft();

            Assert.Throws<InvalidOperationException>(() => karel.Move());
            karel.TurnOff();

            karel.Location.Avenue.Should().Be(1);
            karel.Location.Street.Should().Be(1);
        }

        [Test]
        public void CanReadWorld()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);
            World.ReadWorld("World1.kwld");
            
            karel.TurnOff();
        }

        [Test]
        public void CanPickBeeper()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);
            World.ReadWorld("World2.kwld");

            World.Instance.BeeperLocations.Count.Should().Be(2);
            karel.Move();
            karel.Move();
            karel.TurnLeft();
            karel.Move();
            karel.Move();
            karel.Move();
            karel.Move();
            karel.PickBeeper();

            karel.TurnOff();   
        }

        [Test]
        public void CannotMoveThroughNorthSouthWall()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);
            World.ReadWorld("World1.kwld");

            karel.TurnLeft();
            karel.Move();
            karel.Move();
            karel.Move();
            karel.Move();
            karel.TurnLeft();
            karel.TurnLeft();
            karel.TurnLeft();
            Assert.Throws<InvalidOperationException>(() => karel.Move());

            karel.TurnOff();   
        }

        [Test]
        public void CannotMoveThroughEastWestWall()
        {
            UrRobot karel = new UrRobot(1, 1, Direction.East, 0);
            World.ReadWorld("World1.kwld");

            karel.Move();
            karel.Move();
            karel.TurnLeft();
            karel.Move();
            karel.Move();
            Assert.Throws<InvalidOperationException>(() => karel.Move());

            karel.TurnOff();
        }
    }
}